package com.ericsson.enap.modules.kpi.thread;

import com.ericsson.common.util.*;
import com.ericsson.enap.modules.kpi.entity.*;
import com.ericsson.enap.modules.kpi.service.impl.KpiFileProcessCHFImpl;
import com.googlecode.aviator.Expression;
import org.slf4j.Logger;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * VGC_CHF十五分钟KPI数据处理线程
 */
public class VgcChfFifKpiDataProcessThread implements Runnable {

    private KpiFileProcessCHFImpl kpiFileProcess;
    private Logger log;
    private MongoTemplate mongoTemplate;
    private List<EnipFormula> formulas;
    private String typeStr;
    private Date date;
    private VgcFifKpi vgcFifKpi;
    private String vgckpiDownloadDir;

    public VgcChfFifKpiDataProcessThread(VgcFifKpi vgcFifKpi, String typeStr, List<EnipFormula> formulas, Date date, Logger log, String vgckpiDownloadDir) {
        this.kpiFileProcess = (KpiFileProcessCHFImpl)SpringUtils.getBean("kpiFileProcess" + typeStr + "Impl");
        this.mongoTemplate = (MongoTemplate) SpringUtils.getBean("mongoTemplate");
        this.vgcFifKpi = vgcFifKpi;
        this.typeStr = typeStr;
        this.formulas = formulas;
        this.date = date;
        this.log = log;
        this.vgckpiDownloadDir = vgckpiDownloadDir;
    }

    @Override
    public void run() {
        List<EnipMeasInfo> curDataObj = getData(0, this.vgcFifKpi);
        countAndInsertToDB(curDataObj);
    }

    private List<EnipMeasInfo> getData(int delay, VgcFifKpi vgcFifKpi) {
        try {
            String filePathString = this.vgckpiDownloadDir + File.separator + this.typeStr + File.separator + vgcFifKpi.getId() + File.separator;
            List<File> files = downloadFilesByFTP(vgcFifKpi, delay, filePathString);
            if (files != null&&files.size()>0) {
                return filterAndGetData(files);
            } else {
                log.info("download file null");
            }
        } catch (Exception e) {
            log.error("KpiDataProcessTask getData method:" + e.getMessage() + "netType is :" + this.typeStr, e);
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 从ftp服务器下载文件
     *
     * @param vgcFifKpi
     * @param delay
     * @return
     * @throws Exception
     */
    private List<File> downloadFilesByFTP(VgcFifKpi vgcFifKpi, int delay, String filePathString) throws Exception {
        File filePath = new File(filePathString);
        FileUtil.newDirs(filePath);
        // 删除上一批次下载的文件
        if (filePath.exists()) {
            File[] oldxmlTargetFiles = filePath.listFiles();
            for (File file : oldxmlTargetFiles) {
                if (file.exists() && file.isFile()) {
                    log.info("|||||||||||||||||||||||||||||||||||||||||||||||" + file.getName());
                    file.delete();
                }
            }
        }
        return kpiFileProcess.download(vgcFifKpi, filePathString, log,this.date,0);
    }

    /**
     * 通过各个kpiFileProcess的实现类的analysis方法解析文件
     *
     * @param files
     * @return
     */
    private List<EnipMeasInfo> filterAndGetData(List<File> files) {
        log.info(vgcFifKpi.getName() + "analysis start");
        List<EnipMeasInfo> enipMeasInfoList = kpiFileProcess.analysis(files, log);
        log.info(vgcFifKpi.getName() + "analysis end" + enipMeasInfoList.size());
        return enipMeasInfoList;
    }

    private void countAndInsertToDB(Object curDataObj) {
        if (curDataObj == null) {
            log.error(typeStr + ":" + vgcFifKpi.getName() + "curDataObj null");
            return;
        }
        List<EnipMeasInfo> measInfos = (List<EnipMeasInfo>) curDataObj;
        String beginTime = measInfos.get(0).getBeginTime();
        Query query = Query.query(Criteria.where("dateTime").is(beginTime));
        query.addCriteria(Criteria.where("netid").is(vgcFifKpi.getId().toString()));
        long count = this.mongoTemplate.count(query, "vgckpi_16_" + typeStr.toLowerCase());//统计查询count查询
        log.info("count:" + count + "beginTime:" + beginTime + "netid:" + vgcFifKpi.getId().toString());
        if (count == 0) {
            //循环每一个公式
            Map<String, String> resultMap = new HashMap<>();
            EnipKpiDataResult kpiDataResult = new EnipKpiDataResult();
            try {
                for (EnipFormula formula : formulas) {
                    try {
                        //1 获取编译后的表达式对象
                        Expression compiledExp = formula.getExpression();
                        //2 取出计算因子
                        List<String> vars = compiledExp.getVariableFullNames();
                        //计算公式用的map,key 为计算因子，value 为 对应的值
                        Map<String, Object> dataMap = new HashMap<>();
                        for (String var : vars) {
                            String perVar = FormulaConvertChfFive.restoreFormula(var);
                            //fem类型的CHF
                            if (perVar.contains("femhachf")) {
                                boolean avg=perVar.contains("avg_");
                                boolean sum=perVar.contains("sum_");
                                boolean max=perVar.contains("max_");
                                int countAvg=0;
                                double resultTotal=0.0;
                                for (EnipMeasInfo m : measInfos) {
                                    String result = parseData(m, perVar);
                                    if(avg&&null != result){
                                            countAvg=countAvg+1;
                                            resultTotal=resultTotal+Double.valueOf(result);
                                    }else if(sum&&null != result){
                                            resultTotal=resultTotal+Double.valueOf(result);
                                    }else if(max&&null != result){
                                            resultTotal = resultTotal >= Double.valueOf(result) ? resultTotal : Double.valueOf(result);
                                    }
                                }
                                if(avg) {
                                    countAvg=countAvg==0?1:countAvg;
                                    dataMap.put(var, resultTotal/countAvg);
                                }else{
                                    dataMap.put(var, resultTotal);
                                }
                            }else{
                                //olm类型的CHF
                                for (EnipMeasInfo m : measInfos) {
                                    String result = parseData(m, perVar);
                                    if (null != result && !result.equals("0.0")) {
                                        dataMap.put(var, Double.valueOf(result));
                                    }
                                }
                            }
                            if (!dataMap.containsKey(var)) {
                                dataMap.put(var, Double.valueOf("0.0"));
                            }
                        }
                        if (dataMap.size() > 0) {
                            Object result = AviatorUtil.execute(compiledExp, dataMap, formula);
                            resultMap.put(String.valueOf(formula.getId()), String.valueOf(result));
                        }
                    } catch (Exception ex) {
                        log.error(typeStr + ":" + vgcFifKpi.getName() + ex.getCause());
                    }
                }
            } catch (Exception e) {
                log.error(typeStr + ":" + vgcFifKpi.getName() + e.getCause());
            }
            if (resultMap.size() > 0) {
                kpiDataResult.setDateTime(beginTime);
                kpiDataResult.setNetid(String.valueOf(vgcFifKpi.getId()));
                kpiDataResult.setPoolid(String.valueOf(vgcFifKpi.getPool_id()));
                kpiDataResult.setNetName(vgcFifKpi.getName());
                kpiDataResult.setKpiMap(resultMap);
                log.info("insert data to MongoDB " + typeStr + ":" + vgcFifKpi.getName() + " start ...");
                mongoTemplate.insert(kpiDataResult, "vgckpi_16_" + typeStr.toLowerCase());
                log.info("insert data to MongoDB " + typeStr + ":" + vgcFifKpi.getName() + " end ...");
            } else {
                log.info("nodata：" + vgcFifKpi.getName());
            }
        }
    }

    /**
     * 根据公式中的规则 解析数据
     *
     * @param m
     * @param perVar
     * @return
     */
    private String parseData(EnipMeasInfo m, String perVar) {
        Map<String, EnipMeasValue> mvMap = m.getMeasValueMap();
        String tempVar = perVar;
        int count = 0;
        double calResult = 0;
        perVar = perVar.replace("avg_", "").replace("max_", "").replace("sum_", "");
        if (perVar.contains(".") && m.getMeasTypeMap().containsKey(perVar.split("\\.")[0].replace(FormulaConvertChfFive.__POINT__CHAR__,"."))) {//包含条件
            String[] temp = perVar.split("\\.");
            temp[0]=temp[0].replace(FormulaConvertChfFive.__POINT__CHAR__,".");
            for (String key : mvMap.keySet()) {
                boolean remark = true;
                for (int n = 1; n < temp.length; n++) {
                    if(temp[n].contains(FormulaConvertChfFive.__POINT__CHAR__)){
                        temp[n]=temp[n].replace(FormulaConvertChfFive.__POINT__CHAR__,".");
                    }
                    if (!temp[n].contains("|")) {//条件中不包含|
                        if ((!temp[n].contains("not_contains")||!temp[n].contains("not_startingwith")) && !checkKey(key,temp[n].replace("contains", "").replace("startingwith",""),temp[n])) {
                            remark = false;
                            break;
                        } else if ((temp[n].contains("not_contains")||temp[n].contains("not_startingwith")) && checkKey(key,temp[n].replace("not_contains", "").replace("not_startingwith",""),temp[n])) {
                            remark = false;
                            break;
                        }
                    } else {//条件中包含|
                        String[] tempOr = temp[n].split("\\|");
                        for (int o = 0; o < tempOr.length; o++) {
                            if ((!tempOr[o].contains("not_contains")||!tempOr[o].contains("not_startingwith")) && checkKey(key,tempOr[o].replace("contains", "").replace("startingwith",""),tempOr[o])) {
                                remark = true;
                                break;
                            } else if ((tempOr[o].contains("not_contains")||tempOr[o].contains("not_startingwith")) && !checkKey(key,tempOr[o].replace("not_contains", "").replace("not_startingwith",""),tempOr[o])) {
                                remark = true;
                                break;
                            }else{
                                remark = false;
                            }
                        }
                    }
                }
                if (remark == true) {
                    EnipMeasValue enipMeasValue = mvMap.get(key);
                    if (enipMeasValue.getRMap().containsKey(m.getMeasTypeMap().get(temp[0]))) {
                        calResult = calResult + Double.parseDouble(enipMeasValue.getRMap().get(m.getMeasTypeMap().get(temp[0])));
                        if (tempVar.contains("avg_")) {//包含计算平均值的  计数器
                            count = count + 1;
                        }
                    }
                }
            }
            if (count > 0) {
                return calResult / count + "";
            } else {
                return calResult + "";
            }
        } else {//不包含条件
            if (m.getMeasTypeMap().containsKey(perVar.replace(FormulaConvertChfFive.__POINT__CHAR__,"."))) {
                for (EnipMeasValue enipMeasValue : mvMap.values()) {
                    if (enipMeasValue.getRMap().containsKey(m.getMeasTypeMap().get(perVar.replace(FormulaConvertChfFive.__POINT__CHAR__,".")))) {
                        calResult = calResult + Double.parseDouble(enipMeasValue.getRMap().get(m.getMeasTypeMap().get(perVar.replace(FormulaConvertChfFive.__POINT__CHAR__,"."))));
                        if (tempVar.contains("avg_")) {//包含计算平均值的  计数器
                            count = count + 1;
                        }
                    }
                }
                if (count > 0) {
                    return calResult / count + "";
                } else {
                    return calResult + "";
                }
            }
        }
        return null;
    }

    private boolean checkKey(String key,String value,String valueSelf){
        if(key.contains(",")) {
            String[] keyStr = key.split(",");
            boolean result=false;
            for(int i=0;i<keyStr.length;i++){
                if(valueSelf.contains("contains")){
                    if (keyStr[i].trim().contains(value)) {
                        result = true;
                        break;
                    }
                }else if(valueSelf.contains("startingwith")){
                    if (keyStr[i].trim().startsWith(value)) {
                        result = true;
                        break;
                    }
                }else {
                    if (keyStr[i].trim().equals(value)) {
                        result = true;
                        break;
                    }
                }
            }
            return result;
        }else{
            return key.contains(value);
        }
    }
}
